package com.treasure.infrastructure.domain.llm.qianwen;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.pagehelper.PageHelper;
import com.treasure.common.model.SessionUser;
import com.treasure.common.model.SessionUserHolder;
import com.treasure.common.threadpool.GlobalThreadPoolEnum;
import com.treasure.common.types.InteractionId;
import com.treasure.common.types.Question;
import com.treasure.domain.domain.ChatHistoryDomainService;
import com.treasure.common.model.ChatHistoryEntity;
import com.treasure.domain.domain.entity.ChatHistoryQuery;
import com.treasure.infrastructure.model.po.ChatHistory;
import com.treasure.infrastructure.model.po.ChatHistoryDetail;
import com.treasure.infrastructure.repository.dao.mapper.ChatHistoryDetailMapper;
import com.treasure.infrastructure.repository.dao.mapper.ChatHistoryMapper;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.common.Strings;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;

/**
 * @author sunhongmin
 * @date 2023/9/6 23:18
 * @description
 */
@Service
@Slf4j
public class ChatHistoryDomainServiceImpl implements ChatHistoryDomainService {
    @Resource
    private ChatHistoryMapper chatHistoryMapper;
    @Resource
    private ChatHistoryDetailMapper chatHistoryDetailMapper;

    private final ExecutorService threadPool = GlobalThreadPoolEnum.GLOBAL_BACKTASK_THREAD_POOL.getExecutorService();

    @Override
    public InteractionId createInteractionId(Question question) {
        SessionUser sessionUser = SessionUserHolder.getAndCheckSessionUser();
        ChatHistory chatHistory = new ChatHistory();
        chatHistory.setCorpId(sessionUser.getCorpId());
        chatHistory.setUserId(sessionUser.getUserId());
        chatHistory.setSummaryOfQuestion(question.getValue());
        chatHistory.setCreateTime(LocalDateTime.now());

        chatHistoryMapper.insert(chatHistory);
        return new InteractionId(chatHistory.getId().intValue());
    }

    @Override
    public boolean checkInteractionExists(Integer interactionId) {
        if (Objects.isNull(interactionId)) {
            return false;
        }
        SessionUser sessionUser = SessionUserHolder.getAndCheckSessionUser();
        QueryWrapper<ChatHistory> chatHistoryQueryWrapper = new QueryWrapper<ChatHistory>();
        chatHistoryQueryWrapper.eq("corp_id", sessionUser.getCorpId())
                .eq("id", interactionId);

        return chatHistoryMapper.exists(chatHistoryQueryWrapper);
    }

    @Override
    public void addChatHistory(ChatHistoryEntity chatHistoryEntity) {
        final SessionUser sessionUser = SessionUserHolder.getAndCheckSessionUser();
        // 插入聊天记录
        threadPool.submit(() -> {
            List<ChatHistoryDetail> chatHistoryDetails = Optional.ofNullable(chatHistoryEntity.getChatHistoryBeans())
                    .map(it -> it.stream().map(history -> {
                        LocalDateTime now = LocalDateTime.now();
                        ChatHistoryDetail chatHistoryDetail = new ChatHistoryDetail();
                        chatHistoryDetail.setCorpId(sessionUser.getCorpId());
                        chatHistoryDetail.setUserId(sessionUser.getUserId());
                        chatHistoryDetail.setInteractionId(chatHistoryEntity.getInteractionId().getValue());
                        chatHistoryDetail.setTrace(chatHistoryEntity.getTrace());
                        chatHistoryDetail.setMessageIdentifier(history.getIden());
                        chatHistoryDetail.setMessage(history.getMessage());
                        chatHistoryDetail.setCreateTime(now);
                        return chatHistoryDetail;
                    }))
                    .map(it -> it.collect(Collectors.toList()))
                    .orElse(Collections.emptyList());

            if (CollectionUtils.isEmpty(chatHistoryDetails)) {
                return;
            }

            for (ChatHistoryDetail chatHistoryDetail : chatHistoryDetails) {
                int insertSize = chatHistoryDetailMapper.insert(chatHistoryDetail);
                log.info("addChatHistory sessionUser:{}, insertSize:{}", sessionUser, insertSize);
            }
        });
    }

    @Override
    public ChatHistoryEntity getChatHistoryList(ChatHistoryQuery chatHistoryQuery) {
        // 先时间倒序查到最新记录
        QueryWrapper<ChatHistoryDetail> chatHistoryDetailQueryWrapper = new QueryWrapper<>();
        chatHistoryDetailQueryWrapper.eq("interaction_id", chatHistoryQuery.getInteractionId().getValue())
                .orderBy(true, false, "create_time");

        PageHelper.startPage(1, chatHistoryQuery.getRounds() * 2 + chatHistoryQuery.getRounds()); // 为了不让异常应答项干扰记忆，这里多取一些数据
        List<ChatHistoryDetail> chatHistoryDetailList = chatHistoryDetailMapper.selectList(chatHistoryDetailQueryWrapper);

        // 先取出最新的，再按照正序排列
        List<ChatHistoryEntity.ChatHistoryBean> chatHistoryBeans = Optional.ofNullable(chatHistoryDetailList)
                .map(it -> it.stream()
                        .sorted((a, b) -> a.getId().intValue() - b.getId().intValue())
                        .map(detail -> {
                            ChatHistoryEntity.ChatHistoryBean chatHistoryBean = new ChatHistoryEntity.ChatHistoryBean();
                            chatHistoryBean.setIden(detail.getMessageIdentifier());
                            chatHistoryBean.setMessage(detail.getMessage());
                            return chatHistoryBean;
                        }).collect(Collectors.toList()))
                .orElse(Collections.emptyList());

        // 排除异常应答项
        List<ChatHistoryEntity.ChatHistoryBean> chatHistoryBeansResponse = excludeExceptionMessage(chatHistoryBeans, chatHistoryQuery.getRounds());

        ChatHistoryEntity chatHistoryEntity = new ChatHistoryEntity();
        chatHistoryEntity.setInteractionId(chatHistoryQuery.getInteractionId());
        chatHistoryEntity.setChatHistoryBeans(chatHistoryBeansResponse);
        return chatHistoryEntity;
    }

    /**
     * 排除异常应答项
     * 实现根据指定的轮次获取聊天记录并确保系统-用户、系统-用户这样的顺序，同时丢弃连续的相同角色的消息
     * @param messages
     * @param maxRound
     * @return
     */
    public List<ChatHistoryEntity.ChatHistoryBean> excludeExceptionMessage(List<ChatHistoryEntity.ChatHistoryBean> messages, int maxRound) {
        if (messages == null || messages.isEmpty() || maxRound <= 0) {
            return Collections.emptyList();
        }

        if (messages.size() == 1) {
            return Collections.emptyList();
        }

        List<ChatHistoryEntity.ChatHistoryBean> response = new ArrayList<>();
        int currentRound = 0;
        String lastRole = "";

        for (ChatHistoryEntity.ChatHistoryBean message : messages) {
            if (message.getIden().equals(lastRole)) {
                // 当相同角色相邻时，舍弃前一个 U-U-A -> u-A
                response.remove(response.size() - 1);
            }

            response.add(message);
            lastRole = message.getIden();

            if (message.getIden().equals(ChatHistoryEntity.IdenEnum.ASSISTANT.getValue())) {
                currentRound++;
            }

            // 到达指定轮次时终止
            if (currentRound >= maxRound) {
                break;
            }
        }

        // 兼容上一轮未响应的情况：上一轮问答系统响应异常而无记录 U-A-A -> U-A
        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(response) && response.size() % 2 != 0) {
            response.remove(response.size() - 1);
        }

        return response;
    }


}
